/**
 * new KVue({
 *    data
 * })
 */
class KVue {

    constructor(options) {
        this.$options = options
        this.$data = options.data

        this.observe(this.$data)

        new Compile(options.el, this)
        
        if (options.created) {
            options.created.call(this)
        }
    }

    // 监听数据
    observe(data) {
        if (!data || typeof data !== 'object') {
            return
        }

        if (Array.isArray(data)) {
            // data.forEach(item => {
            //     this.observe(item)
            // })
            return
        }

        // 遍历监听
        Object.keys(data).forEach(key => {
            this.defineReactive(data, key, data[key])
            this.proxyData(key)
        })
    }

    // 数据响应
    defineReactive(obj, key, val) {
        // 递归数据
        this.observe(val);

        const dep = new Dep();

        Object.defineProperty(obj, key, {
            get() {
                Dep.target && dep.addDep(Dep.target, {k: key, v: val})
                return val
            },
            set(newVal) {
                if (newVal === val) {
                    return
                }
                val = newVal
                dep.notify()
            }
        })
    }

    proxyData(key) {
        Object.defineProperty(this, key, {
            get() {
                return this.$data[key]
            },
            set(nv) {
                this.$data[key] = nv
            }
        })
    }

}


// Watcher
class Watcher {

    constructor(vm, key, cb) {
        this.vm = vm
        this.key = key
        this.cb = cb

        Dep.target = this
        this.vm[this.key]
        Dep.target = null
    }

    update(obj) {
        this.cb.call(this.vm, this.vm[this.key])
    }

}


// 用来管理Watcher
class Dep {

    constructor() {
        this.deps = []
    }

    addDep(dep, obj) {
        this.deps.push(dep)
        this.obj = obj
    }

    notify() {
        this.deps.forEach(dep => dep.update(this.obj))
    }

}